home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / Plug-in - WireFrame Renderer / SR_LinePipe.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-14  |  8.7 KB  |  346 lines  |  [TEXT/MPS ]

  1. /******************************************************************************
  2.  **                                                                             **
  3.  **     Module:        SR_LinePipe.c                                             **
  4.  **                                                                          **
  5.  **                                                                          **
  6.  **     Purpose:     Sample Renderer polygon edge pipeline code                  **
  7.  **                                                                          **
  8.  **                                                                          **
  9.  **                                                                          **
  10.  **     Copyright (C) 1996 Apple Computer, Inc.  All rights reserved.          **
  11.  **                                                                          **
  12.  **                                                                          **
  13.  *****************************************************************************/
  14. #include <stdlib.h>
  15. #include <assert.h>
  16.  
  17. #include "QD3D.h"
  18. #include "QD3DErrors.h"
  19. #include "QD3DMath.h"
  20.  
  21. #include "SR_Math.h"
  22. #include "SR.h"
  23. #include "SR_ClipUtilities.h"
  24.  
  25.  
  26. /*===========================================================================*\
  27.  *
  28.  *    Routine:    SR_LinePipe()
  29.  *
  30.  *    Comments:    Handles lines as well as triangles.
  31.  *
  32. \*===========================================================================*/
  33.  
  34. TQ3Status SR_LinePipe(
  35.     TSRPrivate             *srPrivate, 
  36.     TQ3Point3D            *localVertices,
  37.     long                numVertices,
  38.     long                sizeOfLocalVertices,
  39.     TQ3ColorRGB            *color,
  40.     TQ3Vector3D            *normal,
  41.     long                mode)
  42. {
  43.     TQ3Status            status;
  44.     unsigned long        i;
  45.     TQ3RationalPoint4D    *deviceVertices         = NULL;
  46.     TQ3RationalPoint4D    *clippedVertices         = NULL;
  47.     TQ3RationalPoint4D    *renderVertices         = NULL;
  48.     long                clipFound, allOut;
  49.     unsigned long        *clipFlags                 = NULL;
  50.     long                *clippedVerticesFlags     = NULL;
  51.     LineFunction2D        lineFunction;
  52.         
  53.     /*
  54.      *  Get the appropriate rasterization function for the lines
  55.      *  (depth, whether window is clipped or not, etc.
  56.      */
  57.     lineFunction = ((TSRRasterFunctions *)
  58.                         (srPrivate->currentRasterFunctions))->lineFunction;
  59.     
  60.     /*
  61.      *  If we're in "DO_POLYGON" mode, then we have to consider whether
  62.      *  we need to cull or not.
  63.      */
  64.     if (mode == DO_POLYGON) {
  65.         assert(normal != NULL);
  66.         
  67.         /*
  68.          *  We will attempt to do culling if the rank of the upper-left 3x3 
  69.          *  submatrix of the local-to-world matrix is at least 2.  A rank of 3 
  70.          *  means that volumes are transformed into volumes.  A rank of 2 means 
  71.          *    that volumes are transformed onto a plane.  For a rank of 1 (line) or 
  72.          *    0 (point), we bypass the culling stage and just render the line or 
  73.          *  point.
  74.          */
  75.         if (srPrivate->backfacingStyle == kQ3BackfacingStyleRemove &&
  76.             (srPrivate->normalLocalToWorldRank >= 2)) {
  77.                         
  78.             if (normal->x * normal->x + 
  79.                 normal->y * normal->y + 
  80.                 normal->z * normal->z < 1.e-10) {
  81.                 /* 
  82.                  *  Normal vector's length is < 1.e-10 meaning the polygon is 
  83.                  *  degenerate 
  84.                  */
  85.                 return (kQ3Success);
  86.             }
  87.             
  88.             /*
  89.              *  If the local-to-world matrix has a rank of 2, then the eye
  90.              *  in local coordinates is a vector even if the view is a 
  91.              *    perspective transformation.
  92.              */
  93.             if ((srPrivate->cameraType == kQ3CameraTypeOrthographic) ||
  94.                 (srPrivate->normalLocalToWorldRank == 2)) {
  95.  
  96.                 /* Orthographic projection */
  97.                 if ((normal->x * srPrivate->eyeVectorInLocalCoords.x + 
  98.                      normal->y * srPrivate->eyeVectorInLocalCoords.y + 
  99.                      normal->z * srPrivate->eyeVectorInLocalCoords.z < 0.0) ^
  100.                     ((srPrivate->orientationStyle == 
  101.                         kQ3OrientationStyleClockwise))) {
  102.                     /* 
  103.                      *  Backfacing, so cull it 
  104.                      */
  105.                     return (kQ3Success);
  106.                 }
  107.             } else {
  108.                 TQ3Point3D                *point;
  109.                 TQ3Vector3D                eyeVector;
  110.                 
  111.                 /* Perspective projection */
  112.                 point = localVertices;
  113.                 eyeVector.x = srPrivate->eyePointInLocalCoords.x - point->x;
  114.                 eyeVector.y = srPrivate->eyePointInLocalCoords.y - point->y;
  115.                 eyeVector.z = srPrivate->eyePointInLocalCoords.z - point->z;
  116.                 if ((normal->x * eyeVector.x + 
  117.                      normal->y * eyeVector.y + 
  118.                      normal->z * eyeVector.z < 0.0) ^
  119.                     ((srPrivate->orientationStyle == 
  120.                         kQ3OrientationStyleClockwise))) {
  121.                     /* 
  122.                      *  Backfacing, so cull it 
  123.                      */
  124.                     return (kQ3Success);
  125.                 }
  126.             }
  127.         }
  128.     }
  129.  
  130.     /*
  131.      *  Status set to success - if a subsequent memory allocation fails, or a 
  132.      *  called function fails, set to failure and bail out.
  133.      */
  134.     status = kQ3Success;
  135.  
  136.     /*
  137.      *  Allocate device-coordinate vertices
  138.      */
  139.     deviceVertices = malloc(numVertices * sizeof(TQ3RationalPoint4D));
  140.     if (deviceVertices == NULL) {
  141.         status = kQ3Failure;
  142.         goto bail;
  143.     }
  144.  
  145.     /*
  146.      *  Transform local-space line vertices to device space
  147.      */
  148.     Q3Point3D_To4DTransformArray(
  149.         localVertices,
  150.         &srPrivate->transforms.localToDC,  
  151.         deviceVertices,
  152.         numVertices,
  153.         sizeOfLocalVertices, 
  154.         sizeof(TQ3RationalPoint4D));
  155.         
  156.     /*
  157.      *  renderVertices are those that will be rendered. If there is a clip,
  158.      *  then we'll set this to the clipped vertices instead.
  159.      */
  160.     renderVertices = deviceVertices;
  161.     
  162.     /*
  163.      *  Allocate a clip flag for each vertex. Bail if allocation fails.
  164.      */
  165.     clipFlags = malloc(numVertices * sizeof(unsigned long));
  166.     if (clipFlags == NULL) {
  167.         status = kQ3Failure;
  168.         goto bail;
  169.     }
  170.  
  171.     /*
  172.      *  See if we have a clip
  173.      */
  174.     SRPointList_ClipTestVertices(
  175.         deviceVertices, 
  176.         clipFlags, 
  177.         numVertices, 
  178.         &srPrivate->clipPlanesInDC[0], 
  179.         &clipFound, 
  180.         &allOut, 
  181.         sizeof(TQ3RationalPoint4D));
  182.  
  183.     if (allOut) {
  184.         /*
  185.          *  Return now, as nothing need be drawn
  186.          */
  187.         goto bail;
  188.     }
  189.     
  190.     /*
  191.      *  We've found a clip, so generate the clipped vertext list
  192.      */
  193.     if (clipFound) {
  194.         long    numberOfClippedVertices;
  195.  
  196.         /*
  197.          *  Allocate space for clipped vertices. There will be at most
  198.          *  twice as many of these as there are in the original geometric
  199.          *  primitive. Bail if allocation fails.
  200.          */
  201.         clippedVertices = 
  202.             malloc((numVertices << 1) * sizeof(TQ3RationalPoint4D));
  203.         if (clippedVertices == NULL) {
  204.             status = kQ3Failure;
  205.             goto bail;
  206.         }
  207.         
  208.         /*
  209.          *  Allocate space for clip flags for vertices. Bail if allocation
  210.          *  fails.
  211.          */
  212.         clippedVerticesFlags = malloc((numVertices << 1) * sizeof(long));
  213.         if (clippedVerticesFlags == NULL) {
  214.             status = kQ3Failure;
  215.             goto bail;
  216.         }
  217.  
  218.         /*
  219.          *  Generate the clipped vertex list
  220.          */
  221.         SRPointList_ClipVertices(
  222.             deviceVertices, 
  223.             sizeof(TQ3RationalPoint4D),
  224.             clippedVertices, 
  225.             sizeof(TQ3RationalPoint4D),
  226.             clipFlags, 
  227.             clippedVerticesFlags,
  228.             numVertices, 
  229.             &numberOfClippedVertices,
  230.             &srPrivate->clipPlanesInDC[0],
  231.             mode);
  232.  
  233.         if (numberOfClippedVertices == 0) {
  234.             goto bail;
  235.         }
  236.         
  237.         renderVertices = clippedVertices;
  238.         numVertices = numberOfClippedVertices;
  239.     }
  240.  
  241.     /*
  242.      *  Divide by homogeneous coordinate, but only if
  243.      *    we've NOT found a clip - in that case, the w divide has
  244.      *    already been done...
  245.      */
  246.     if (!clipFound) {
  247.         SRPointList_WDivide(
  248.             renderVertices, 
  249.             numVertices, 
  250.             sizeof(TQ3RationalPoint4D));
  251.     }        
  252.  
  253. #if DEBUGGING
  254.     if (FLOAT_ROUND_TO_LONG_POSITIVE(renderVertices[0].x) < srPrivate->clipPlanesInDC[0]) {
  255.         goto bail;        
  256.     }
  257.     if (FLOAT_ROUND_TO_LONG_POSITIVE(renderVertices[0].x) > srPrivate->clipPlanesInDC[1]) {
  258.         goto bail;        
  259.     }
  260.     if (FLOAT_ROUND_TO_LONG_POSITIVE(renderVertices[0].y) < srPrivate->clipPlanesInDC[2]) {
  261.         goto bail;        
  262.     }
  263.     if (FLOAT_ROUND_TO_LONG_POSITIVE(renderVertices[0].y) > srPrivate->clipPlanesInDC[3]) {
  264.         goto bail;        
  265.     }
  266.     if (FLOAT_ROUND_TO_LONG_POSITIVE(renderVertices[1].x) < srPrivate->clipPlanesInDC[0]) {
  267.         goto bail;        
  268.     }
  269.     if (FLOAT_ROUND_TO_LONG_POSITIVE(renderVertices[1].x) > srPrivate->clipPlanesInDC[1]) {
  270.         goto bail;        
  271.     }
  272.     if (FLOAT_ROUND_TO_LONG_POSITIVE(renderVertices[1].y) < srPrivate->clipPlanesInDC[2]) {
  273.         goto bail;        
  274.     }
  275.     if (FLOAT_ROUND_TO_LONG_POSITIVE(renderVertices[1].y) > srPrivate->clipPlanesInDC[3]) {
  276.         goto bail;        
  277.     }
  278. #endif  /*  DEBUGGING  */
  279.  
  280.  
  281.     /*
  282.      *  Draw line segments between each pair of vertices, taking into
  283.      *  account the clipping information where appropriate.
  284.      */
  285.     for (i = 0; i < numVertices - 1; i++) {
  286.         if (!clipFound                 || 
  287.             (clippedVerticesFlags     && 
  288.              clippedVerticesFlags[i] & SR_DRAW_NEXT)) {
  289.             if ((*lineFunction)(
  290.                     srPrivate,
  291.                     (TQ3Point3D *)&renderVertices[i], 
  292.                     (TQ3Point3D *)&renderVertices[i + 1], 
  293.                     color) == kQ3Failure) {
  294.                 status = kQ3Failure;
  295.                 goto bail;
  296.             }
  297.         }
  298.     }
  299.  
  300.     /*
  301.      *  If we're in "polygon" mode, then we have to connect the last
  302.      *  vertex with the first.
  303.      */
  304.     if (mode == DO_POLYGON) {
  305.         if (!clipFound                 || 
  306.             (clippedVerticesFlags     && 
  307.              clippedVerticesFlags[numVertices - 1] & SR_DRAW_NEXT)) {
  308.             if ((*lineFunction)(
  309.                     srPrivate,
  310.                     (TQ3Point3D *)&renderVertices[numVertices - 1], 
  311.                     (TQ3Point3D *)&renderVertices[0], 
  312.                     color) == kQ3Failure) {
  313.                 status = kQ3Failure;
  314.                 goto bail;
  315.             }
  316.         }
  317.     }
  318.  
  319. bail:
  320.     /*
  321.      *  Free up any allocated memory
  322.      */
  323.     if (deviceVertices != NULL) {
  324.         free(deviceVertices);
  325.     }
  326.     
  327.     if (clipFlags != NULL) {
  328.         free(clipFlags);
  329.     }
  330.     
  331.     if (clippedVertices != NULL) {
  332.         free(clippedVertices);
  333.     }
  334.     
  335.     if (clippedVerticesFlags != NULL) {
  336.         free(clippedVerticesFlags);
  337.     }
  338.     
  339.     /*
  340.      *  Status may be success or failure, the latter being the case if 
  341.      *  an allocation failed or if the line rasterization function returns
  342.      *  failure.
  343.      */
  344.     return (status);
  345. }
  346.